using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Collections;
using System.Threading;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Net;
using Unregistry;
using Microsoft.Win32;
using System.Security.Permissions;

namespace Unregistry.ApplicationController
{
    public partial class Controller
    {
        #region Members
        private MainView _MainView;
        #endregion

        #region Methods
        private void MainView_Show()
        {
            // Instantiate an instance
            this._MainView = new MainView();

            this._MainView.buttonOpenFileDialog.Click += 
                new EventHandler(MainView_buttonOpenFileDialog_Click);
            this._MainView.buttonRemove.Click += 
                new EventHandler(MainView_buttonRemove_Click);
            this._MainView.buttonExit.Click += 
                new EventHandler(MainView_buttonExit_Click);
            this._MainView.FormClosing += 
                new FormClosingEventHandler(MainView_FormClosing);

            // Attach the MainView to the Application Context
            this._AppContext.MainForm = this._MainView;

            // Show the form
            this._MainView.Show();
        }

        #region Event Handlers
        [RegistryPermissionAttribute(SecurityAction.Demand, Unrestricted = true)]
        private void MainView_buttonRemove_Click(object sender, EventArgs e)
        {
            Application.DoEvents();

            Button theRemoveButton =
                sender as Button;
            MainView theParentView =
                theRemoveButton.FindForm() as MainView;

            if (theParentView.IsFormValid())
            {
                try
                {
                    FileInfo theFileInfo = new FileInfo(
                        theParentView.textboxRegistryFile.Text);

                    if (theFileInfo.Exists)
                    {
                        theRemoveButton.Enabled = false;

                        theParentView.ClearLog();

                        switch (MessageBox.Show(
                            theParentView,
                            "Are you sure you want to remove these registry entries?",
                            theParentView.Text,
                            MessageBoxButtons.YesNo,
                            MessageBoxIcon.Question,
                            MessageBoxDefaultButton.Button2))
                        {
                            case DialogResult.No:
                                return;
                        }

                        theParentView.AddLogMessage(
                            LogAction.Information,
                            "Removal Started");

                        Regex thePathRegex =
                            new Regex(@"\[(([^\\]*)[^\]]*)\]", RegexOptions.IgnoreCase);
                        string thisPath = String.Empty;

                        Regex theValueRegex =
                            new Regex(@"""(.*)""=", RegexOptions.IgnoreCase);
                        string thisValue = String.Empty;

                        foreach (string thisLine in File.ReadAllLines(theFileInfo.FullName))
                        {
                            if (thePathRegex.Matches(thisLine).Count > 0)
                            {
                                Match thisMatch =
                                    thePathRegex.Matches(thisLine)[0];

                                thisPath =
                                    thisMatch.Groups[1].Value;
                            }
                            else if (!String.IsNullOrEmpty(thisPath) &&
                                theValueRegex.Matches(thisLine).Count > 0)
                            {
                                Match thisMatch =
                                    theValueRegex.Matches(thisLine)[0];

                                thisValue =
                                    thisMatch.Groups[1].Value;
                            }

                            if (!String.IsNullOrEmpty(thisPath) &&
                                !String.IsNullOrEmpty(thisValue))
                            {
                                RegistryKey thisKey =
                                    Controller.GetHive(thisPath).OpenSubKey(
                                        thisPath.Substring(thisPath.IndexOf("\\") + 1), 
                                        true);

                                if (null != thisKey)
                                {
                                    thisKey.DeleteValue(thisValue, false);

                                    theParentView.AddLogMessage(
                                        LogAction.Value,
                                        String.Format(
                                            CultureInfo.CurrentCulture,
                                            @"Value: ""{0}\{1}"" deleted successfully",
                                            thisKey.ToString(),
                                            thisValue));

                                    if (theParentView.checkboxRemoveEmptyKeys.Checked)
                                    {
                                        Controller.DeleteRegistryKey(
                                            theParentView,
                                            thisKey);
                                    }

                                    thisValue = String.Empty;
                                }
                            }
                        }

                        theParentView.AddLogMessage(
                            LogAction.Information,
                            "Removal Completed");
                    }
                    else
                    {
                        throw new FileNotFoundException();
                    }
                }
                catch (Exception theException)
                {
                    theParentView.ShowErrorProvider(
                        theParentView.buttonOpenFileDialog,
                        theException.Message);
                }
                finally
                {
                    theRemoveButton.Enabled = true;
                }
            }
        }

        private void MainView_buttonOpenFileDialog_Click(
            object sender, 
            EventArgs e)
        {
            Application.DoEvents();

            Button theOpenFileDialogButton =
                sender as Button;
            MainView theParentView =
                theOpenFileDialogButton.FindForm() as MainView;

            switch (theParentView.OpenFileDialog.ShowDialog(theParentView))
            {
                case DialogResult.OK:
                    theParentView.textboxRegistryFile.Text =
                        theParentView.OpenFileDialog.FileName;
                    break;
            }
        }

        private void MainView_buttonExit_Click(
            object sender,
            EventArgs e)
        {
            Application.DoEvents();

            Button theExitButton =
                sender as Button;
            MainView theParentView =
                theExitButton.FindForm() as MainView;

            theParentView.Close();
        }

        private void MainView_FormClosing(
            object sender, 
            FormClosingEventArgs e)
        {
            Application.DoEvents();

            MainView theParentView =
                sender as MainView;
        }
        #endregion

        #region Private Helpers
        public static void DeleteRegistryKey(
            MainView theParentView,
            RegistryKey theKey)
        {
            string theKeyPath =
                theKey.ToString();

            if (theKey.ValueCount.Equals(0) &&
                theKey.SubKeyCount.Equals(0))
            {
                RegistryKey thisParentKey =
                    Controller.GetParentKey(theKey);

                string thisKeyName =
                    theKeyPath.Substring(
                        theKeyPath.LastIndexOf("\\") + 1);

                thisParentKey.DeleteSubKey(thisKeyName, false);

                theParentView.AddLogMessage(
                    LogAction.Key,
                    String.Format(
                        CultureInfo.CurrentCulture,
                        @"Empty Key: ""{0}"" deleted successfully",
                        theKey));

                Controller.DeleteRegistryKey(
                    theParentView,
                    thisParentKey);
            }
        }

        public static RegistryKey GetParentKey(
            RegistryKey theKey)
        {
            string theKeyPath =
                theKey.ToString();

            string thisParentPath =
                theKeyPath.Substring(
                    0, theKeyPath.LastIndexOf("\\"))
                    .Substring(
                        theKeyPath.IndexOf("\\") + 1);

            string thisKeyName =
                theKeyPath.Substring(
                    theKeyPath.LastIndexOf("\\") + 1);

            return Controller.GetHive(theKey)
                .OpenSubKey(thisParentPath, true);
        }

        public static RegistryKey GetHive(
            RegistryKey theKey)
        {
            string theKeyPath =
                theKey.ToString();

            switch (theKeyPath.Substring(
                0, theKeyPath.IndexOf("\\")))
            {
                case "HKEY_LOCAL_MACHINE":
                    return Registry.LocalMachine;
                case "HKEY_CURRENT_USER":
                    return Registry.CurrentUser;
                case "HKEY_CLASS_ROOT":
                    return Registry.ClassesRoot;
                case "HKEY_USERS":
                    return Registry.Users;
                case "HKEY_CURRENT_CONFIG":
                    return Registry.CurrentConfig;
            }
            return null;
        }
        
        public static RegistryKey GetHive(
            string theKeyPath)
        {
            switch (theKeyPath.Substring(
                0, theKeyPath.IndexOf("\\")))
            {
                case "HKEY_LOCAL_MACHINE":
                    return Registry.LocalMachine;
                case "HKEY_CURRENT_USER":
                    return Registry.CurrentUser;
                case "HKEY_CLASS_ROOT":
                    return Registry.ClassesRoot;
                case "HKEY_USERS":
                    return Registry.Users;
                case "HKEY_CURRENT_CONFIG":
                    return Registry.CurrentConfig;
            }
            return null;
        }
        #endregion
        #endregion
    }
}
